package com.deer.wms.instock.web;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.deer.wms.ASN.manage.constant.AsnManageConstant;
import com.deer.wms.ASN.manage.dao.AsnDetailMapper;
import com.deer.wms.ASN.manage.model.Lines;
import com.deer.wms.ASN.manage.model.MiscellaneousVo;
import com.deer.wms.ASN.manage.model.asn.AsnDetail;
import com.deer.wms.ASN.manage.model.asn.AsnMaster;
import com.deer.wms.ASN.manage.model.asn.AsnMasterCriteria;
import com.deer.wms.ASN.manage.model.asn.AsnMasterDto;
import com.deer.wms.ASN.manage.model.in.AcceptRecord;
import com.deer.wms.ASN.manage.model.in.AcceptRecordCriteria;
import com.deer.wms.ASN.manage.service.AcceptRecordService;
import com.deer.wms.ASN.manage.service.AsnMasterService;
import com.deer.wms.base.system.constant.BaseSystemConstant;
import com.deer.wms.base.system.dao.ErpBackRecordMapper;
import com.deer.wms.base.system.model.Cell.CellInfo;
import com.deer.wms.base.system.model.Cell.CellInfoDto;
import com.deer.wms.base.system.model.erp.ErpInConstant;
import com.deer.wms.base.system.service.CellInfoService;
import com.deer.wms.base.system.service.ErpService;
import com.deer.wms.base.system.service.ItemInfoService;
import com.deer.wms.busine.tactic.model.Upper.UpperTacticDetailDto;
import com.deer.wms.instock.constant.InStockConstant;
import com.deer.wms.instock.model.Allot.TransferBillCriteria;
import com.deer.wms.instock.model.ProcurementVo;
import com.deer.wms.instock.model.ReturnGoodsVo;
import com.deer.wms.instock.model.transfer.*;
import com.deer.wms.instock.service.TransferBillService;
import com.deer.wms.intercept.annotation.User;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventoryCriteria;
import com.deer.wms.inventory.model.Inventory.InventoryDto;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.lzb.erp.service.ErpRecordService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.core.result.Result;
import com.deer.wms.project.root.core.result.ResultGenerator;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.util.StringUtils;
import com.deer.wms.system.manage.model.user.UserInfo;
import com.deer.wms.system.manage.service.CellLedService;
import com.deer.wms.system.manage.service.UserInfoService;
import com.deer.wms.ware.task.dao.PickTaskMapper;
import com.deer.wms.ware.task.model.ErpPushLogInfo;
import com.deer.wms.ware.task.model.SO.SoMasterCriteria;
import com.deer.wms.ware.task.model.SO.SoMasterDto;
import com.deer.wms.ware.task.service.SoMasterService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.annotations.ApiIgnore;

import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * @author : wei
 * @since : 2022-01-08 20:37:44
 **/
@Api(description = "转移单API接口")
@RestController
@RequestMapping("/transfer")
public class TransferBillController {
    @Value("${prj.name}")
    private String prjName;

    @Autowired
    private TransferBillService transferBillService;
    @Autowired
    private AcceptRecordService acceptRecordService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private CellInfoService cellInfoService;
    @Autowired
    private ItemInfoService itemInfoService;
    @Autowired
    private AsnMasterService asnMasterService;
    @Autowired
    private AsnDetailMapper asnDetailMapper;
    @Autowired
    private ErpService erpService;
    @Autowired
    private ErpBackRecordMapper erpBackRecordMapper;
    @Autowired
    private TransferBillController transferBillController;
    @Autowired
    private CellLedService cellLedService;
    @Autowired
    private SoMasterService soMasterService;
    @Autowired
    private PickTaskMapper pickTaskMapper;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private ErpRecordService erpRecordService;


    @ApiOperation(value = "上架", notes = "PDA")
    @PostMapping("create/upper")
    @Transactional
    public Result createUpper(@RequestBody UpperData upperData, @ApiIgnore @User CurrentUser currentUser) {
        //遍历数据，逐一上架
        List<Upper> upperList = upperData.getUpperList();
        List<TransferBill> transferBills = new ArrayList<>();
        List<String> cellCodes = new ArrayList<>();
        String areaCode = "";
        if (upperList != null && upperList.size() > 0) {
            for (Upper upper : upperList) {
                //Step1.校验数据
                Inventory fromInv = inventoryService.getById(upper.getFromInvId());
                if (ObjectUtil.isNull(fromInv)) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未找到对应的库存");
                }
                if (InventoryConstant.TRANSACT_STATE_UNNORMAL.equals(fromInv.getState())) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "物料未质检，禁止上架!");
                }
                CellInfoDto cellInfo = cellInfoService.findByCodeAndWareId(upper.getCellCode(), fromInv.getWareId());
                if (ObjectUtil.isNull(cellInfo)) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "不存在库位【" + upper.getCellCode() + "】,请确认!");
                } else {
                    if (ObjectUtil.notEqual(cellInfo.getCellUseType(), BaseSystemConstant.CELL_USE_TYPE_STORE)) {
                        throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "库位【" + upper.getCellCode() + "】不为存储库位,请确认!");
                    }
                }
                //Step2.封装数据
                TransferBill transferBill = createAndHandleUpperData(currentUser, upper, fromInv);
                transferBills.add(transferBill);

                cellCodes.add(upper.getCellCode());
                areaCode = cellInfo.getAreaCode();
            }
            //Step3.保存上架单并确认上架
            transferBillService.saveAndConfirmTransferBill(transferBills);

            //卓品上架成功后灭等
            cellLedService.ledControl(cellCodes, null, null, 0);
            //Step4.回传接口
//            if (ObjectUtil.equal("zp", this.prjName)) {
//                AsnDetail asnDetail = asnDetailMapper.findByInventoryId(upperList.get(0).getFromInvId());
//                UserInfo userInfo = userInfoService.getById(currentUser.getUserId());
//                sentToErp(upperList, asnDetail, areaCode, userInfo.getJobNumber());
//            } else if (ObjectUtil.equal("jy", this.prjName)) {
//                transferBillService.createUpper(upperData);
//            }
        } else {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "数据错误，请联系管理员检查!");
        }
        return ResultGenerator.genSuccessResult(transferBills);
    }

    private void sentToErp(List<Upper> upperList, AsnDetail asnDetail, String areaCode, String userCode) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (asnDetail != null) {
            Double qty = upperList.get(0).getQuantity();
            AsnMaster asnMaster = asnMasterService.getOneByField("bill_no", asnDetail.getBillNo());
             if (ObjectUtil.equal(ErpInConstant.ERP_IN_TYPE_SALESRETURN, asnMaster.getAsnType())) {
                //166销售退货
                List<ReturnGoodsVo> returnGoodsVos = new ArrayList<>();
                ReturnGoodsVo returnGoodsVo = new ReturnGoodsVo();
                returnGoodsVo.setDocNo(asnDetail.getBillNo());//退回处理单号
                returnGoodsVo.setDocLineNo(asnDetail.getErpLineNo());//退回处理单行号
                returnGoodsVo.setTransQty(qty);//退货数量
                returnGoodsVos.add(returnGoodsVo);
                //回传erp
                Map<String, Object> returnMap = new HashMap<>();
                Map<String, Object> requestMap = new HashMap<>();
                try {
                    requestMap.put("data", returnGoodsVos);
                    requestMap.put("msg", "请求");
                    requestMap.put("code", 200);
                    erpRecordService.erpLog(requestMap, ErpInConstant.ERP_IN_TYPE_SALESRETURN);
                    returnMap = doPostOrGet(ErpInConstant.ERP_IN_RETURL_SALESRETURN, JSONObject.toJSONString(returnGoodsVos));
                    if (returnMap.get("code") == null || !"200".equals(returnMap.get("code").toString())) {
                        throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "销售退货回传失败，具体原因：" + returnMap.get("msg").toString());
                    }
                } finally {
                    erpRecordService.erpLog(returnMap, ErpInConstant.ERP_IN_TYPE_SALESRETURN);
                }
//            } else if (ObjectUtil.equal(ErpInConstant.ERP_IN_TYPE_PRDRETURN, asnMaster.getAsnType())) {
//                //生产退料
//                List<ProductionReturn> productionReturns = new ArrayList<>();
//                ProductionReturn productionReturn = new ProductionReturn();
//                productionReturn.setMo(asnDetail.getMo());//生产订单ID
//                productionReturn.setMoPick(Long.parseLong(asnDetail.getMoPick()));//生产订单备料ID
//                productionReturn.setRtnQty(qty);//退料数量
//                productionReturn.setRtnReason(0);//退料原因(   0  倒扣退料  ，1  委外退料  ， 2   盘点差异退料)
//                productionReturns.add(productionReturn);
//                //回传erp
//                Map<String, Object> returnMap = new HashMap<>();
//                Map<String, Object> requestMap = new HashMap<>();
//                try {
//                    requestMap.put("data", productionReturns);
//                    requestMap.put("msg", "请求");
//                    requestMap.put("code", 200);
//                    erpRecordService.erpLog(requestMap, ErpInConstant.ERP_IN_TYPE_PRDRETURN);
//                    returnMap = doPostOrGet(ErpInConstant.ERP_IN_RETURL_PRDRETURN, JSONObject.toJSONString(productionReturns));
//                    if (returnMap.get("code") == null || !"200".equals(returnMap.get("code").toString())) {
//                        throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "生产退料回传失败，具体原因：" + returnMap.get("msg").toString());
//                    }
//                } finally {
//                    erpRecordService.erpLog(returnMap, ErpInConstant.ERP_IN_TYPE_PRDRETURN);
//                }
//            } else if (ObjectUtil.equal(ErpInConstant.ERP_IN_TYPE_PRD, asnMaster.getAsnType())) {
//                //168完工报告???
//                List<CompletionReport> completionReports = new ArrayList<>();
//                CompletionReport completionReport = new CompletionReport();
//                completionReport.setMoCode(asnDetail.getBillNo());//生产订单编码
//                completionReport.setCompleteQty(qty);//完工数量 (完工 = 合格 + 报废 + 返工)
//                completionReport.setEligibleQty(qty);//合格数量
//                completionReport.setScrapQty(0d);//报废数量
//                completionReport.setReworkQty(0d);//返工数量
//                completionReports.add(completionReport);
//                //回传erp
//                Map<String, Object> returnMap = new HashMap<>();
//                Map<String, Object> requestMap = new HashMap<>();
//                try {
//                    requestMap.put("data", completionReports);
//                    requestMap.put("msg", "请求");
//                    requestMap.put("code", 200);
//                    erpRecordService.erpLog(requestMap, ErpInConstant.ERP_IN_TYPE_PRD);
//                    returnMap = doPostOrGet(ErpInConstant.ERP_IN_RETURL_PRD, JSONObject.toJSONString(completionReports));
//                    if (returnMap.get("code") == null || !"200".equals(returnMap.get("code").toString())) {
//                        throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "完工报告回传失败，具体原因:" + returnMap.get("msg").toString());
//                    }
//                } finally {
//                    erpRecordService.erpLog(returnMap, ErpInConstant.ERP_IN_TYPE_PRD);
//                }

            }
        } else {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未查询到ERP源单，请联系管理员检查!");
        }
    }

    private TransferBill createAndHandleUpperData(CurrentUser currentUser, Upper upper, Inventory fromInv) {
        TransferBill transferBill = new TransferBill();
        //仓库 转移单类型
        transferBill.setWareId(fromInv.getWareId());
        transferBill.setBillType(InStockConstant.TRANS_TYPE_UPPER);
        //库位
        transferBill.setFromCellCode(fromInv.getCellCode());
        transferBill.setToCellCode(upper.getCellCode());
        //容器
        transferBill.setFromBoxCode(fromInv.getBoxCode());
        transferBill.setToBoxCode(fromInv.getBoxCode());
        transferBill.setItemCode(fromInv.getItemCode());
        transferBill.setBatchId(fromInv.getBatchId());
        transferBill.setBatchName(fromInv.getBatchName());
        BigDecimal transQty = StringUtils.isNotEmpty(upper.getBoxCode()) ? BigDecimal.valueOf(fromInv.getQuantity()) :
                BigDecimal.valueOf(upper.getQuantity());
        transferBill.setQty(transQty);
        transferBill.setFromInvId(upper.getFromInvId());
        //确认人
        transferBill.setConfirmUserId(currentUser.getUserId());
        transferBill.setConfirmUserName(currentUser.getUserName());
        return transferBill;
    }

    @ApiOperation(value = "转移", notes = "PDA")
    @PostMapping("create/transfer")
    public Result createTransferForPda(@RequestBody Upper upper, @ApiIgnore @User CurrentUser currentUser) {
        //Step1.准备数据
        TransferBill transferBill = new TransferBill();
        //转移单类型
        transferBill.setBillType(InStockConstant.TRANS_TYPE_MOVE);
        //来源容器库存
        Inventory boxIvt = inventoryService.getOneByField("box_code", upper.getBoxCode());
        if (ObjectUtil.isNull(boxIvt)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "根据追踪号：" + upper.getBoxCode() + "未找到对应的库存");
        }
        //已分配的库存不允许转移
        if(boxIvt.getAllotQuantity() > 0.0) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "当前追踪号已被拣货分配，禁止转移!");
        }
        //冻结的物料可以被转移
//        if (InventoryConstant.TRANSACT_STATE_UNNORMAL.equals(boxIvt.getState())) {
//            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器内物料未质检，禁止转移!");
//        }
        //判断目标库位是否合法
        CellInfo cellInfo = cellInfoService.getOneByField("cell_code", upper.getCellCode());
        if (ObjectUtil.isNull(cellInfo)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未查询到目标库位:[" + upper.getCellCode() + "]!");
        }
        if (ObjectUtil.notEqual(BaseSystemConstant.CELL_USE_TYPE_STORE, cellInfo.getCellUseType())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "库位:[" + upper.getCellCode() + "]不为存储库位，不允许转移!");
        }

        //仓库
        transferBill.setWareId(boxIvt.getWareId());
        //来源库位
        transferBill.setFromCellCode(boxIvt.getCellCode());
        //目标库位
        transferBill.setToCellCode(upper.getCellCode());
        //来源容器
        transferBill.setFromBoxCode(upper.getBoxCode());
        transferBill.setItemCode(boxIvt.getItemCode());
        transferBill.setBatchName(boxIvt.getBatchName());
        transferBill.setBatchId(boxIvt.getBatchId());
        transferBill.setPackDetailId(boxIvt.getPackDetailId());
        transferBill.setQty(new BigDecimal(boxIvt.getQuantity()));
        //确认人
        transferBill.setConfirmUserId(currentUser.getUserId());
        transferBill.setConfirmUserName(currentUser.getUserName());
        transferBill.setFromInvId(boxIvt.getInventoryId());
        //Step2.保存
        transferBillService.saveAndConfirmTransferBill(ListUtil.toList(transferBill));

        List<String> cellCodes = new ArrayList<>();
        cellCodes.add(upper.getCellCode());
        cellLedService.ledControl(cellCodes, null, null, 0);
        return ResultGenerator.genSuccessResult();
    }

    /*private void extracted(CurrentUser currentUser, String cellCode, String batchName, List<TransferBill> transferBills) {
        //上架回传erp
        List<AcceptRecord> billNos = acceptRecordService.findBillNo(transferBills.get(0).getFromBoxCode());

        Integer erpAreaId = cellInfoService.findbyCellCode(cellCode);
        //初始化回传数据
        AsnMaster asnMaster = asnMasterMapper.selectOne(new QueryWrapper<AsnMaster>().eq("bill_no", billNos.get(0).getAsnBillNo()));
        BaseAssist enterAssist = new BaseAssist();

       *//* enterAssist.setFromBoxCode(transferBills.get(0).getFromBoxCode());
        enterAssist.setDeptId(dept.getDeptId());
        enterAssist.setCellCode(cellCode);
        enterAssist.setBatchName(batchName);
        enterAssist.setErpAreaId(erpAreaId);*//*


        QueryWrapper<TransferBill> tbqw = Wrappers.query();
        TransferBill tb = transferBillMapper.selectOne(tbqw.eq("to_box_code", transferBills.get(0).getFromBoxCode()));
        QueryWrapper<AsnDetail> adqw = Wrappers.query();
        AsnDetail asnDetail = asnDetailMapper.selectOne(adqw.eq("detail_no", tb.getUda2()));
        asnDetail.setQty(tb.getQty().doubleValue()); //数量
        asnDetail.setStockId(erpAreaId); //仓库id
        asnDetail.setBatchName(inventoryService.getOne(new QueryWrapper<Inventory>().eq("box_code", transferBills.get(0).getFromBoxCode())).getBillNo());
        List<AsnDetail> asnDetails = new ArrayList<>();
        asnDetails.add(asnDetail);
//        strategyEnterService.resolveAsn(asnMaster, asnDetails, enterAssist);


        //获取库区编码
        LambdaQueryWrapper<CellInfo> cellInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        cellInfoLambdaQueryWrapper.eq(CellInfo::getCellCode, cellCode);
        CellInfo one = cellInfoService.getOne(cellInfoLambdaQueryWrapper);
        if (one == null) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "库位为空");
        }
        ShelfInfo shelfInfo = shelfInfoMapper.selectById(one.getShelfInfoId());
        if (shelfInfo == null) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "库位组为空");
        }
        AreaInfo areaInfo = areaInfoMapper.selectById(shelfInfo.getAreaId());
        if (areaInfo == null) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "库区为空");
        }
        AcceptRecord acceptRecord = billNos.get(0);
        //1999 采购收货 2000 销售退货  2001 生产退料 2002 完工报告 2003 采购退货 2004 销售出货 2005 生产领料 2006 调拨出库
        //入库回传
        if (asnMaster.getAsnType().intValue() == 1999) {
            List<ProcurementVo> procurementVos = new ArrayList<>();
            asnDetails.stream().forEach(t -> {
                ProcurementVo procurementVo = new ProcurementVo();
                procurementVo.setAsnNo(t.getBillNo());//asn单号
                procurementVo.setAsnLineNo(t.getErpLineNo());//asn单行号
                procurementVo.setTransQty(acceptRecord.getQuantity());//收货数量
                procurementVo.setWhCode(areaInfo.getAreaCode());//存储地点
                if (StringUtils.isEmpty(currentUser.getUserCode())) {
                    currentUser.setUserCode("026");
                }
                procurementVo.setKgCode(currentUser.getUserCode());//业务员
                procurementVos.add(procurementVo);
            });

            //回传erp
            Map<String, Object> returnMap = new HashMap<>();
            try {
                returnMap = doPostOrGet("http://61.160.125.186:5555/zp/api/ZpViewAsn/Create", JSONObject.toJSONString(procurementVos));
                if (returnMap.get("code") == null || !"200".equals(returnMap.get("code").toString())) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "采购收货回传失败，具体原因:" + returnMap.get("msg").toString());
                }
            } finally {
                transferBillController.erpLog(returnMap, asnMaster.getAsnType().intValue());
            }
        } else if (asnMaster.getAsnType().intValue() == 2000) {//166销售退货
            List<ReturnGoodsVo> returnGoodsVos = new ArrayList<>();
            asnDetails.stream().forEach(t -> {
                ReturnGoodsVo returnGoodsVo = new ReturnGoodsVo();
                returnGoodsVo.setDocNo(t.getBillNo());//退回处理单号
                returnGoodsVo.setDocLineNo(t.getErpLineNo());//退回处理单行号
                returnGoodsVo.setTransQty(acceptRecord.getQuantity());//退货数量
                returnGoodsVos.add(returnGoodsVo);
            });
            //回传erp
            Map<String, Object> returnMap = new HashMap<>();
            try {
                returnMap = doPostOrGet("http://61.160.125.186:5555/zp/api/ZpViewRtnRcv/Create", JSONObject.toJSONString(returnGoodsVos));
                if (returnMap.get("code") == null || !"200".equals(returnMap.get("code").toString())) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "销售退货回传失败，具体原因：" + returnMap.get("msg").toString());
                }
            } finally {
                transferBillController.erpLog(returnMap, asnMaster.getAsnType().intValue());
            }
        } else if (asnMaster.getAsnType().intValue() == 2001) {//167生产退料
            List<ProductionReturn> productionReturns = new ArrayList<>();
            asnDetails.stream().forEach(t -> {
                ProductionReturn productionReturn = new ProductionReturn();
                productionReturn.setMo(t.getMo());//生产订单ID
                productionReturn.setMoPick(Long.parseLong(t.getMoPick()));//生产订单备料ID
                productionReturn.setRtnQty(acceptRecord.getQuantity());//退料数量
                productionReturn.setRtnReason(0);//退料原因(   0  倒扣退料  ，1  委外退料  ， 2   盘点差异退料)
                productionReturns.add(productionReturn);
            });
            //回传erp
            Map<String, Object> returnMap = new HashMap<>();
            try {
                returnMap = doPostOrGet("http://61.160.125.186:5555/zp/api/ZpViewRtnPick/Create", JSONObject.toJSONString(productionReturns));
                if (returnMap.get("code") == null || !"200".equals(returnMap.get("code").toString())) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "生产退料回传失败，具体原因：" + returnMap.get("msg").toString());
                }
            } finally {
                transferBillController.erpLog(returnMap, asnMaster.getAsnType().intValue());
            }
        } else if (asnMaster.getAsnType().intValue() == 2002) {//168完工报告
            List<CompletionReport> completionReports = new ArrayList<>();
            asnDetails.stream().forEach(t -> {
                CompletionReport completionReport = new CompletionReport();
                completionReport.setMoCode(t.getBillNo());//生产订单编码
//                completionReport.setCompleteQty(t.getAcceptQuantity());//完工数量 (完工 = 合格 + 报废 + 返工)
//                completionReport.setEligibleQty(t.getAcceptQuantity());//合格数量
                completionReport.setCompleteQty(acceptRecord.getQuantity());//完工数量 (完工 = 合格 + 报废 + 返工)
                completionReport.setEligibleQty(acceptRecord.getQuantity());//合格数量
                completionReport.setScrapQty(0d);//报废数量
                completionReport.setReworkQty(0d);//返工数量
                completionReports.add(completionReport);
            });
            //回传erp
            Map<String, Object> returnMap = new HashMap<>();
            try {
                returnMap = doPostOrGet("http://61.160.125.186:5555/zp/api/ZpViewConplete/Create", JSONObject.toJSONString(completionReports));
                if (returnMap.get("code") == null || !"200".equals(returnMap.get("code").toString())) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "完工报告回传失败，具体原因:" + returnMap.get("msg").toString());
                }
            } finally {
                transferBillController.erpLog(returnMap, asnMaster.getAsnType().intValue());
            }
        }
    }*/

    /**
     * 调用第三方接口
     *
     * @param pathUrl 地址
     * @param data    参数
     * @return
     */
    public static Map<String, Object> doPostOrGet(String pathUrl, String data) {
        System.out.println("=================================================");
        System.out.println(data);
        System.out.println("=================================================");
        OutputStreamWriter out = null;
        BufferedReader br = null;
        String result = "";
        Map<String, Object> map = new HashMap<>();
        try {
            URL url = new URL(pathUrl);
            //打开和url之间的连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //请求方式
            conn.setRequestMethod("POST");
            //conn.setRequestMethod("GET");

            //设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");

            //DoOutput设置是否向httpUrlConnection输出，DoInput设置是否从httpUrlConnection读入，此外发送post请求必须设置这两个
            conn.setDoOutput(true);
            conn.setDoInput(true);

            /**
             * 下面的三句代码，就是调用第三方http接口
             */
            //获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
            //发送请求参数即数据
            out.write(data);
            //flush输出流的缓冲
            out.flush();

            /**
             * 下面的代码相当于，获取调用第三方http接口后返回的结果
             */
            //获取URLConnection对象对应的输入流
            InputStream is = conn.getInputStream();
            //构造一个字符流缓存
            br = new BufferedReader(new InputStreamReader(is));
            String str = "";
            while ((str = br.readLine()) != null) {
                result += str;
            }
            map = JSON.parseObject(result);
            System.out.println(result);
            //关闭流
            is.close();
            //断开连接，disconnect是在底层tcp socket链接空闲时才切断，如果正在被其他线程使用就不切断。
            conn.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return map;
    }


    public static Map<String, Object> getDateFromERP(String url, HttpMethod method, List<ProcurementVo> list) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//        String str = JSONObject.toJSONString(list);
//        str = str.replace("\\","");
//        JSONArray jsona =(JSONArray) JSONArray.parse(jsonn);
//        JSONObject json = JSONObject.parseObject(str);

        String str = JSONObject.toJSONString(list);
        str = str.replace('[', ' ').replace(']', ' ');
        JSONObject json = JSONObject.parseObject(str);
        HttpEntity<JSONObject> requestEntity = new HttpEntity<>(json, headers);
        RestTemplate client = new RestTemplate();
        ResponseEntity<String> response = client.exchange(url, method, requestEntity, String.class);
        String res = response.getBody();
        JSONObject object = JSON.parseObject(res);

        Integer code = object.getInteger("code");
        String msg = object.getString("msg");
        String data = object.getString("data");
        String result = object.getString("result");
        Map<String, Object> resulTmap = new HashMap<>();
        resulTmap.put("msg", msg);
        resulTmap.put("code", code);
        resulTmap.put("data", data);
        resulTmap.put("result", result);
        return resulTmap;
    }

    @GetMapping("/report/data")
    public Result getReportData(@RequestParam Integer wareId) {
        Map<String, Object> map = new HashMap<>();
        //今日出入库订单数
        AsnMasterCriteria asnMasterCriteria = new AsnMasterCriteria();
        asnMasterCriteria.setStartCreateTime(DateUtil.today());
        asnMasterCriteria.setEndCreateTime(DateUtil.format(DateUtil.offsetDay(new Date(), 1), "yyyy-MM-dd"));
        List<AsnMasterDto> asnMasterDtos = asnMasterService.findList(asnMasterCriteria);

        SoMasterCriteria soMasterCriteria = new SoMasterCriteria();
        soMasterCriteria.setStartCreateTime(DateUtil.today());
        soMasterCriteria.setEndCreateTime(DateUtil.format(DateUtil.offsetDay(new Date(), 1), "yyyy-MM-dd"));
        List<SoMasterDto> soMasterDtos = soMasterService.findList(soMasterCriteria);

        map.put("inBillNum", asnMasterDtos.size());
        map.put("outBillNum", soMasterDtos.size());

        //收货
        AcceptRecordCriteria acceptRecordCriteria = new AcceptRecordCriteria();
        AcceptRecordCriteria acceptRecordCriteria2 = new AcceptRecordCriteria();
        AcceptRecordCriteria acceptRecordCriteria3 = new AcceptRecordCriteria();
        AcceptRecordCriteria acceptRecordCriteria4 = new AcceptRecordCriteria();
        AcceptRecordCriteria acceptRecordCriteria5 = new AcceptRecordCriteria();
        acceptRecordCriteria.setStartAcceptTime(DateUtil.today());
        acceptRecordCriteria.setEndAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), 1), "yyyy-MM-dd"));
        acceptRecordCriteria2.setStartAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), -1), "yyyy-MM-dd"));
        acceptRecordCriteria2.setEndAcceptTime(DateUtil.today());
        acceptRecordCriteria3.setStartAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), -2), "yyyy-MM-dd"));
        acceptRecordCriteria3.setEndAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), -1), "yyyy-MM-dd"));
        acceptRecordCriteria4.setStartAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), -3), "yyyy-MM-dd"));
        acceptRecordCriteria4.setEndAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), -2), "yyyy-MM-dd"));
        acceptRecordCriteria5.setStartAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), -4), "yyyy-MM-dd"));
        acceptRecordCriteria5.setEndAcceptTime(DateUtil.format(DateUtil.offsetDay(new Date(), -3), "yyyy-MM-dd"));
        List<AcceptRecord> dayList = acceptRecordService.findDayList(acceptRecordCriteria);
        List<AcceptRecord> dayList2 = acceptRecordService.findDayList(acceptRecordCriteria2);
        List<AcceptRecord> dayList3 = acceptRecordService.findDayList(acceptRecordCriteria3);
        List<AcceptRecord> dayList4 = acceptRecordService.findDayList(acceptRecordCriteria4);
        List<AcceptRecord> dayList5 = acceptRecordService.findDayList(acceptRecordCriteria5);

        Map<String, Double> map2 = new TreeMap<String, Double>(
                new Comparator<String>() {
                    @Override
                    public int compare(String obj1, String obj2) {
                        // 降序排序
                        return obj1.compareTo(obj2);
                    }
                });
        String today = DateUtil.today();
        String today_1 = DateUtil.format(DateUtil.offsetDay(new Date(), -1), "yyyy-MM-dd");
        String today_2 = DateUtil.format(DateUtil.offsetDay(new Date(), -2), "yyyy-MM-dd");
        String today_3 = DateUtil.format(DateUtil.offsetDay(new Date(), -3), "yyyy-MM-dd");
        String today_4 = DateUtil.format(DateUtil.offsetDay(new Date(), -4), "yyyy-MM-dd");
        map2.put(today, dayList.stream().map(AcceptRecord::getQuantity).reduce(0.0, Double::sum));
        map2.put(today_1, dayList2.stream().map(AcceptRecord::getQuantity).reduce(0.0,
                Double::sum));
        map2.put(today_2, dayList3.stream().map(AcceptRecord::getQuantity).reduce(0.0,
                Double::sum));
        map2.put(today_3, dayList4.stream().map(AcceptRecord::getQuantity).reduce(0.0,
                Double::sum));
        map2.put(today_4, dayList5.stream().map(AcceptRecord::getQuantity).reduce(0.0,
                Double::sum));

        map.put("inTrend", map2);

        //发货确认
        Map<String, Double> map3 = new TreeMap<String, Double>(
                new Comparator<String>() {
                    @Override
                    public int compare(String obj1, String obj2) {
                        // 降序排序
                        return obj1.compareTo(obj2);
                    }
                });
        map3.put(today, pickTaskMapper.getSendOutStockByDate(DateUtil.today(), DateUtil.format(DateUtil.offsetDay(new Date(), 1), "yyyy-MM-dd")));
        map3.put(today_1, pickTaskMapper.getSendOutStockByDate(today_1, today));
        map3.put(today_2, pickTaskMapper.getSendOutStockByDate(today_2, today_1));
        map3.put(today_3, pickTaskMapper.getSendOutStockByDate(today_3, today_2));
        map3.put(today_4, pickTaskMapper.getSendOutStockByDate(today_4, today_3));
        map.put("outTrend", map3);

        return ResultGenerator.genSuccessResult(CommonCode.SUCCESS, map);
    }


    @ApiOperation(value = "容器编码查是否为其他类型入库")
    @GetMapping("/packwork/findByCode")
    public Result selectPackWorkList(String code) {
        if (ObjectUtil.isEmpty(code)) {
            return null;
        }
        Map<String, Object> map = acceptRecordService.finbyCode(code);
        return ResultGenerator.genSuccessResult(map);
    }

    @ApiOperation(value = "查询上架单")
    @GetMapping("/putaway/select")
    public Result selectPackingList(TransferBillCriteria criteria) {
        // 设置单据类型
        criteria.setBillType(InStockConstant.TRANS_TYPE_UPPER);
        // 设置页面的分页条件
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        // 根据条件查询上架单数据
        List<TransferBill> transferBills = transferBillService.selectBillList(criteria);
        // 封装分页的数据
        PageInfo pageInfo = new PageInfo(transferBills);
        // 返回成功的结果
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @ApiOperation(value = "查询转移单")
    @GetMapping("/transferBill/list")
    public Result selectTransferBill(TransferBillCriteria criteria) {
        // 设置单据类型--4(转移单)
        criteria.setBillType(InStockConstant.TRANS_TYPE_MOVE);

        // 设置页面的分页条件
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        // 根据条件查询上架单数据
        List<TransferBill> transferBills = transferBillService.selectBillList(criteria);
        // 封装分页的数据
        PageInfo pageInfo = new PageInfo(transferBills);
        // 返回成功的结果
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @PostMapping("/transferBill/insert")
    @ApiOperation(value = "添加转移单", notes = "添加转移单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result addTransferBill(@RequestBody TransferBillCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            // 没有登录
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER, null);
        }
        List<TransferBill> transferBills = new ArrayList<>();
        TransferBill transferBill = new TransferBill();
        //仓库
        transferBill.setWareId(criteria.getWareId());
        //转移单类型
        transferBill.setBillType(InStockConstant.TRANS_TYPE_MOVE);
        //来源库位 收货区库位
        Inventory boxIvt = inventoryService.getOneByField("box_code", criteria.getFromBoxCode());
        if (ObjectUtil.isNull(boxIvt)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "根据容器号：" + criteria.getFromBoxCode() + "未找到对应的库存");
        }
        //FIXME: 这里写死，冻结的物料不能转移
        if (InventoryConstant.TRANSACT_STATE_UNNORMAL.equals(boxIvt.getState())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器内物料未质检，禁止上架!");
        }
        transferBill.setFromCellCode(boxIvt.getCellCode());
        //目标库位
        transferBill.setToCellCode(criteria.getToCellCode());
        //来源容器
        transferBill.setFromBoxCode(criteria.getFromBoxCode());
        transferBill.setItemCode(boxIvt.getItemCode());
        transferBill.setBatchName(boxIvt.getBatchName());
        transferBill.setPackDetailId(boxIvt.getPackDetailId());
        transferBill.setQty(new BigDecimal(boxIvt.getQuantity()));
        //标记冻结解冻标识
        if (boxIvt.getFreezeQuantity() > 0) {
            //说明是待检的物料
            transferBill.setFreezeFlag(AsnManageConstant.ACCEPT_QC_STATE_TODO);
        }
        //确认人
        transferBill.setConfirmUserId(currentUser.getUserId());
        transferBill.setConfirmUserName(currentUser.getUserName());
        transferBill.setConfirmTime(DateUtil.now());
        transferBills.add(transferBill);
        //Step2.保存
        transferBillService.createTransferBill(transferBills);
        return ResultGenerator.genSuccessResult();
    }


    @PostMapping("/PackWork/insert")
    @ApiOperation(value = "添加装箱单", notes = "添加装箱单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result addPackWork(@RequestBody TransferBillCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            // 没有登录
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER, null);
        }
        // 数据复制
        TransferBill transferBill = new TransferBill();
        // 装箱的数据来源库位和目标库位一样
        BeanUtils.copyProperties(criteria, transferBill);
        transferBill.setToCellCode(criteria.getFromCellCode());
        // 设置操作人员编号
        transferBill.setConfirmUserId(currentUser.getUserId());
        transferBill.setConfirmUserName(currentUser.getUserName());
        transferBill.setConfirmTime(DateUtil.now());
        // 设置转移单类型
        transferBill.setBillType(InStockConstant.TRANS_TYPE_PACK_BOX);
        // 准备数据
        List<TransferBill> transferBills = new ArrayList<>();
        transferBills.add(transferBill);
        // 执行保存的方法 saveAndConfirmTransferBill 保存会直接确认不使用这个方法
        transferBillService.createTransferBill(transferBills);
        // 新增成功返回消息
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/transferBill/updateState")
    @ApiOperation(value = "转移单确认", notes = "转移单确认")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result updateState(@RequestBody TransferBillCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            // 没有登录
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER, null);
        }
//        // 准备数据
//        criteria.setBillType(InStockConstant.TRANS_TYPE_MOVE);
        List<TransferBill> transferBills = transferBillService.selectBillList(criteria);
        // 执行转移单确认的方法
        transferBillService.confirmTransferBill(transferBills);
        // 新增成功返回消息
        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "上架推荐库位")
    @GetMapping("/upper/recommend")
    public Result recommendUpperCellForPDA(@RequestParam String boxCode) {
        //Step1.校验容器库存是否是待收货区的
        InventoryCriteria inventoryCriteria = new InventoryCriteria();
        inventoryCriteria.setBoxCode(boxCode);
        List<InventoryDto> list = inventoryService.findList(inventoryCriteria);
        if (list.size() == 0) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器：[" + boxCode + "]未查询到库存");
        }
        if (ObjectUtil.notEqual(BaseSystemConstant.CELL_USE_TYPE_ACCEPT.toString(), list.get(0).getCellUseType())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器：[" + boxCode + "]库存在不收货区");
        }
        if (list.size() > 1) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器：[" + boxCode + "]存在多条数据");
        }

        //Step2.找到对应的上架策略
        InventoryDto inventoryDto = list.get(0);
        String itemCode = inventoryDto.getItemCode();
        List<UpperTacticDetailDto> upperTacticDetails = itemInfoService.findUpperTacticDetails(itemCode);

        //Step3.根据策略找到满足条件的库位
        List<CellInfoDto> recommendUpperCells = new ArrayList<>();
        for (UpperTacticDetailDto upperTacticDetail : upperTacticDetails) {
            recommendUpperCells = cellInfoService.getRecommendUpperCells(upperTacticDetail);
            //暂时只处理一个
            break;
        }
        for (CellInfoDto recommendUpperCell : recommendUpperCells) {
            Integer boxNum = inventoryService.getBoxNumInCell(recommendUpperCell.getCellCode());
            recommendUpperCell.setBoxNum(boxNum);
        }

        return ResultGenerator.genSuccessResult(recommendUpperCells);
    }

    @GetMapping("saveBillOutInfo")
    public Result saveBillOutInfo(String date) {
//      ?  transferBillService.saveBillOutInfo(date);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("virtual")
    public Result virtual(String detailIds, @ApiIgnore @User CurrentUser currentUser) {
        List<String> detailId = Arrays.asList(detailIds.split(","));
        transferBillService.virtual(detailId, currentUser);
        return ResultGenerator.genSuccessResult();
    }


    @PostMapping("/updateErpLog/{id}")
    public Result updateErpLog(@RequestBody List<ErpPushLogInfo> erpPushLogInfo, @PathVariable Integer id) {
        transferBillService.updateErpLog(erpPushLogInfo, id);
        return ResultGenerator.genSuccessResult();
    }


    @GetMapping("getErpBill")
    @ApiOperation(value = "获取入库数据源")
    public Result getErpBill(String billTypeId) {
        Map<String, Object> map = new HashMap<>();
        map.put("billTypeId", billTypeId);
        asnMasterService.savePurchaseOrder(map);
        return ResultGenerator.genSuccessResult();
    }
}
